`include "defines.v"
module id(
	input wire rst,
	input wire[31:0] pc_i,
	input wire[31:0] inst_i,
	input wire[31:0] reg1_data_i,
	input wire[31:0] reg2_data_i,
	output reg[4:0] reg1_addr_o,
	output reg[4:0] reg2_addr_o,
	output reg reg1_read_o,
	output reg reg2_read_o,
	//传给id_ex模块的信号
	output reg[31:0] reg1_o,
	output reg[31:0] reg2_o,
	output reg[4:0] reg3_addr_o,
	output reg reg3_write_o,
	output reg[`AluOpWidth-1:0] alu_op_o,
	// output reg[`AluSelWidth-1:0] alu_sel_o
	
	//执行模块传给译码模块的信号（解决数据相关）
	input wire[4:0] ex_write_addr_i,
	input wire ex_write_ce_i,
	input wire[31:0] ex_write_data_i,
	//访存模块传给译码模块的信号（解决数据相关）
	input wire[4:0] mem_write_addr_i,
	input wire mem_write_ce_i,
	input wire[31:0] mem_write_data_i
);
	reg[31:0] imm;
	reg inst_valid;
	//主要译码逻辑
	always@(*)
		if(rst == `RstEnable) 
		begin
			reg1_addr_o = `NOPRegAddr;
			reg2_addr_o = `NOPRegAddr;
			reg1_read_o = `ReadDisable;
			reg2_read_o = `ReadDisable;
			reg3_addr_o = 5'b0;
			reg3_write_o = `WriteDisable;
			alu_op_o =  `ALU_NOP_OP;
			// alu_sel_o = `ALU_RES_NOP;
			imm = `ZeroWord;
			inst_valid = `InstInvalid;
		end
		else 
		begin
			// reg1_addr_o = inst_i[25:21]; //reg1_addr_o默认代表rs地址
			// reg2_addr_o = inst_i[20:16]; //reg2_addr_o默认代表rt地址
			// reg1_read_o = `ReadDisable; //默认读无效
			// reg2_read_o = `ReadDisable; //默认读无效
			// reg3_addr_o = inst_i[15:11]; //reg3_addr_o默认代表rd地址
			// reg3_write_o = `WriteDisable; //默认写无效
			// alu_op_o =  `ALU_NOP_OP; //默认ALU空操作
			// alu_sel_o = `ALU_RES_NOP; //默认空类型运算
			// imm = `ZeroWord; //默认立即数为0
			// inst_valid = `InstInvalid; //默认指令无效
			reg1_addr_o = 5'b00000; 
			reg2_addr_o = 5'b00000; 
			reg1_read_o = `ReadDisable; 
			reg2_read_o = `ReadDisable;
			reg3_addr_o = 5'b00000; 
			reg3_write_o = `WriteDisable;
			alu_op_o =  `ALU_NOP_OP; 
			// alu_sel_o = `ALU_RES_NOP; 
			imm = `ZeroWord; 
			inst_valid = `InstInvalid;
			case(inst_i[31:26])
				`INST_ORI:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_OR_OP; 
					// alu_sel_o = `ALU_RES_LOGIC; 
					imm = {16'b0, inst_i[15:0]};
					inst_valid = `InstValid;
				end
				`INST_ANDI:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_AND_OP; 
					imm = {16'b0, inst_i[15:0]};
					inst_valid = `InstValid;
				end
				`INST_XORI:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_XOR_OP; 
					imm = {16'b0, inst_i[15:0]};
					inst_valid = `InstValid;
				end
				`INST_LUI:
				begin
					reg1_addr_o = 5'b00000; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadDisable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LUI_OP; 
					imm = {inst_i[15:0], 16'b0};
					inst_valid = `InstValid;
				end
				`INST_PREF:
				begin
					reg1_addr_o = 5'b00000; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadDisable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_NOP_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				6'b000000:
				begin
					case(inst_i[5:0])
						`INST_AND:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_AND_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_OR:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_OR_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_XOR:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_XOR_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_NOR:
						begin
						reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_NOR_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SLLV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SLL_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SRLV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRL_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SRAV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRA_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SYNC:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_NOP_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SLL:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SLL_OP; 
							imm = inst_i[10:6]; 
							inst_valid = `InstValid;
						end
						`INST_SRL:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRL_OP; 
							imm = inst_i[10:6]; 
							inst_valid = `InstValid;
						end
						`INST_SRA:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRA_OP; 
							imm = inst_i[10:6]; 
							inst_valid = `InstValid;
						end
						
						`INST_MOVN:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = (reg2_o == `ZeroWord)? `WriteDisable : `WriteEnable;
							alu_op_o =  `ALU_MOVN_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MOVZ:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = (reg2_o == `ZeroWord)? `WriteEnable : `WriteDisable;
							alu_op_o =  `ALU_MOVZ_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MFHI:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadDisable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_MFHI_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MFLO:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadDisable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_MFLO_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MTHI:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MTHI_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MTLO:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MTLO_OP; 
							imm = `ZeroWord; 
						end
						default:
						begin 
						end
					endcase
				end
				default:
				begin 
				end
			endcase
		end
			
		
	//为reg1_o赋值逻辑
	always@(*)
		if(rst == `RstEnable)
			reg1_o = `ZeroWord;		
		else if(reg1_read_o == `ReadDisable)
			reg1_o = imm;
			
		//从执行模块拿数据
		else if(reg1_read_o == `ReadEnable &&
				reg1_addr_o == ex_write_addr_i &&
				ex_write_ce_i == `WriteEnable)
			reg1_o = ex_write_data_i;
		//从访存模块拿数据
		else if(reg1_read_o == `ReadEnable &&
				reg1_addr_o == mem_write_addr_i &&
				mem_write_ce_i == `WriteEnable)
			reg1_o = mem_write_data_i;	
		
		else if(reg1_read_o == `ReadEnable)
			reg1_o = reg1_data_i;
		else
			reg1_o = `ZeroWord;
			
	//为reg2_o赋值逻辑
	always@(*)
		if(rst == `RstEnable)
			reg2_o = `ZeroWord;
		else if(reg2_read_o == `ReadDisable)
			reg2_o = imm;
		
		//从执行模块拿数据
		else if(reg2_read_o == `ReadEnable &&
				reg2_addr_o == ex_write_addr_i &&
				ex_write_ce_i == `WriteEnable)
			reg2_o = ex_write_data_i;
		//从访存模块拿数据
		else if(reg2_read_o == `ReadEnable &&
				reg2_addr_o == mem_write_addr_i &&
				mem_write_ce_i == `WriteEnable)
			reg2_o = mem_write_data_i;	
			
			
		else if(reg2_read_o == `ReadEnable)
			reg2_o = reg2_data_i;
		else
			reg2_o = `ZeroWord;
endmodule